package org.springblade.modules.client;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.xiaoymin.knife4j.annotations.ApiOperationSupport;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springblade.common.constant.RedisKeyConstant;
import org.springblade.common.utils.ThreadPool;
import org.springblade.core.log.exception.ServiceException;
import org.springblade.core.mp.support.Condition;
import org.springblade.core.mp.support.Query;
import org.springblade.core.redis.cache.BladeRedis;
import org.springblade.core.secure.utils.AuthUtil;
import org.springblade.core.tool.api.R;
import org.springblade.core.tool.utils.BeanUtil;
import org.springblade.core.tool.utils.CollectionUtil;
import org.springblade.core.tool.utils.Func;
import org.springblade.core.tool.utils.ObjectUtil;
import org.springblade.modules.classes.entity.TeacherEvaluateEntity;
import org.springblade.modules.classes.service.ITeacherEvaluateService;
import org.springblade.modules.classes.vo.TeacherEvaluateVO;
import org.springblade.modules.classes.wrapper.TeacherEvaluateWrapper;
import org.springblade.modules.course.entity.CourseEntity;
import org.springblade.modules.course.service.ICourseService;
import org.springblade.modules.course.vo.CourseVO;
import org.springblade.modules.classes.entity.TrainingPlanCourseEntity;
import org.springblade.modules.classes.entity.TrainingPlanEntity;
import org.springblade.modules.classes.service.ITrainingPlanCourseService;
import org.springblade.modules.classes.service.ITrainingPlanService;
import org.springblade.modules.classes.vo.TrainingPlanVO;
import org.springblade.modules.classes.wrapper.TrainingPlanWrapper;
import org.springblade.modules.system.entity.User;
import org.springblade.modules.system.service.IUserService;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import springfox.documentation.annotations.ApiIgnore;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;


/**
 * 培训计划表 客户端
 *
 * @author junxin
 * @since 2023-05-10
 */
@RestController
@AllArgsConstructor
@RequestMapping("blade-client/trainingPlan")
@Api(value = "客户端培训计划相关接口", tags = "客户端培训计划相关接口")
public class ClientTrainingPlanController {

	private final ITrainingPlanService trainingPlanService;
	private final ITrainingPlanCourseService trainingPlanCourseService;
	private final ICourseService courseService;
	private final BladeRedis bladeRedis;
	private final IUserService userService;
	private final ITeacherEvaluateService teacherEvaluateService;

	/**
	 * 培训计划表 详情
	 */
	@GetMapping("/detail")
	@ApiOperationSupport(order = 1)
	@ApiOperation(value = "培训计划及其下所有课程", notes = "传入trainingPlan")
	public R<TrainingPlanVO> detail(TrainingPlanEntity trainingPlan) {
		TrainingPlanEntity detail = trainingPlanService.getOne(Condition.getQueryWrapper(trainingPlan));
		List<TrainingPlanCourseEntity> trainingPlanCourseList = trainingPlanCourseService.queryListByWrappers(Wrappers.<TrainingPlanCourseEntity>query().lambda().eq(TrainingPlanCourseEntity::getTrainingPlanId, detail.getId()));
		TrainingPlanVO resultVo = TrainingPlanWrapper.build().entityVO(detail);
		List<CourseVO> courseEntityList = new ArrayList<>();
		if (CollectionUtil.isNotEmpty(trainingPlanCourseList)) {
			//返回结果添加该培训计划下的所有课程
			trainingPlanCourseList.forEach(trainingPlanCourseEntity -> {
				CourseEntity courseEntity = courseService.getById(trainingPlanCourseEntity.getCourseId());
				if (null != courseEntity) {
					CourseVO courseVO = new CourseVO();
					BeanUtil.copyProperties(courseEntity, courseVO);
					courseEntityList.add(courseVO);
				}
			});
		}
		resultVo.setCourseList(courseEntityList);
		return R.data(resultVo);
	}


	/**
	 * 已过期的培训计划 分页
	 */
	@GetMapping("/myself-expire-list")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "已过期的培训计划分页列表", notes = "")
	public R myselfTrainingPlanlist(@ApiIgnore @RequestParam Map<String, Object> trainingPlan, Query query) {
		List<Long> trainPlanIds=trainingPlanService.getUserTrainingPlanIds(AuthUtil.getUserId());
		if (null==trainPlanIds)return R.success("暂无数据");
		List<TrainingPlanEntity> trainingPlanEntityList=trainingPlanService.list(Wrappers.<TrainingPlanEntity>query().lambda()
			.in(TrainingPlanEntity::getId, trainPlanIds));

		Date now=new Date();
		//筛选已过期的培训记录
		List<TrainingPlanEntity> filterTrainingPlanList = trainingPlanEntityList.stream()
			.filter(trainingPlanEntity -> trainingPlanEntity.getEndTime().before(now)).collect(Collectors.toList());
		if (CollectionUtil.isEmpty(filterTrainingPlanList))  return  R.success("无培训记录");

		//筛选后的培训计划ids
		trainPlanIds=filterTrainingPlanList.stream().map(TrainingPlanEntity::getId).collect(Collectors.toList());
		IPage<TrainingPlanEntity> pages = trainingPlanService.page(Condition.getPage(query), Condition.getQueryWrapper(trainingPlan, TrainingPlanEntity.class)
			.in("id",trainPlanIds));
		IPage<TrainingPlanVO> trainingPlanVOIPage = TrainingPlanWrapper.build().pageVO(pages);
		trainingPlanVOIPage.setRecords(trainingPlanService.trainingPlanDetail(trainPlanIds,trainingPlanVOIPage.getRecords()));//给每条培训计划赋予对应的课程详情
		return R.data(trainingPlanVOIPage);
	}

	/**
	 * 待评价的教师列表
	 * 展示该培训计划下的课程 对应的老师列表
	 */
	@GetMapping("/teacher-evaluate-list")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "待评价的教师列表", notes = "传入培训计划主键:planId")
	public R teacherEvaluate(Long planId) {
		if (Func.isEmpty(planId)) throw new ServiceException("请先选择培训计划");
		Long userId = AuthUtil.getUserId();
		//旧的评价数据 为空则正常
		List<TeacherEvaluateEntity> oldTeacherEvaluateList = teacherEvaluateService.list(Wrappers.<TeacherEvaluateEntity>query().lambda()
			.eq(TeacherEvaluateEntity::getPlanId, planId).eq(TeacherEvaluateEntity::getUserId, userId));
		if (Func.isNotEmpty(oldTeacherEvaluateList)) throw new ServiceException("您已评价过了,请勿重复评价");

		List<TeacherEvaluateVO> resultList=new ArrayList<>();
		//1。根据培训计划主键 查询出对应的课程及老师
		List<TrainingPlanCourseEntity> trainingPlanCourseList = trainingPlanCourseService.list(Wrappers.<TrainingPlanCourseEntity>query()
			.lambda().eq(TrainingPlanCourseEntity::getTrainingPlanId, planId));
		if (Func.isNotEmpty(trainingPlanCourseList)) {
			List<Long> courseIdList = trainingPlanCourseList.stream().map(TrainingPlanCourseEntity::getCourseId).collect(Collectors.toList());

			List<CourseEntity> courseEntityList = courseService.list(Wrappers.<CourseEntity>query().lambda().in(CourseEntity::getId,courseIdList));
			if (Func.isNotEmpty(courseEntityList)) {
				for (CourseEntity course:courseEntityList){
					TeacherEvaluateVO evaluateVO=new TeacherEvaluateVO();
					evaluateVO.setCourseName(course.getName());
					evaluateVO.setCourseId(course.getId());
					evaluateVO.setPlanId(planId);

					//部分课程无设置老师，则对应的课程不需要进行评价
					if (Func.isNotEmpty(course.getTeacherId())){
						User user = userService.getById(course.getTeacherId());
						if (Func.isNotEmpty(user) && Func.isNotEmpty(user.getRealName())){
							evaluateVO.setTeacherId(course.getTeacherId());
							evaluateVO.setTeacherName(user.getRealName());
							resultList.add(evaluateVO);
						}

					}
				}
			}
		}
		return R.data(resultList);
	}

	@PostMapping("/save-teacher-evaluate")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "提交评价", notes = "评价列表，包含courseId,teacherId,planId,score")
	@Transactional(rollbackFor = Exception.class)
	public R submitTeacherEvaluate(@RequestBody @Valid TeacherEvaluateVO teacherEvaluateVO) {
		if (Func.isEmpty(teacherEvaluateVO.getPlanId())) throw new ServiceException("请先选择培训计划");

		Long userId = AuthUtil.getUserId();
		Long planId=teacherEvaluateVO.getPlanId();
		//旧的评价数据 为空则正常
		List<TeacherEvaluateEntity> oldTeacherEvaluateList = teacherEvaluateService.list(Wrappers.<TeacherEvaluateEntity>query().lambda()
			.eq(TeacherEvaluateEntity::getPlanId, planId).eq(TeacherEvaluateEntity::getUserId, userId));
		if (Func.isNotEmpty(oldTeacherEvaluateList)) throw new ServiceException("您已评价过了,请勿重复评价");

		List<TeacherEvaluateEntity> teacherEvaluateList = teacherEvaluateVO.getTeacherEvaluateList();
		if (Func.isNotEmpty(teacherEvaluateList)){
			teacherEvaluateList.forEach(teacherEvaluateEntity -> {
				teacherEvaluateEntity.setPlanId(planId);
				teacherEvaluateEntity.setUserId(userId);
			});
			teacherEvaluateService.saveBatch(teacherEvaluateList);
		}

		return R.success("操作成功");
	}

	@GetMapping("/myself-teacher-evaluate")
	@ApiOperationSupport(order = 2)
	@ApiOperation(value = "我的教师评价", notes = "传入培训计划主键:planId")
	public R myselfTeacherEvaluate(Long planId) {
		if (Func.isEmpty(planId)) throw new ServiceException("请先选择培训计划");
		Long userId = AuthUtil.getUserId();
		//旧的评价数据
		List<TeacherEvaluateEntity> oldTeacherEvaluateList = teacherEvaluateService.list(Wrappers.<TeacherEvaluateEntity>query().lambda()
			.eq(TeacherEvaluateEntity::getPlanId, planId).eq(TeacherEvaluateEntity::getUserId, userId));
		if (Func.isEmpty(oldTeacherEvaluateList)) throw new ServiceException("您尚未评价过,请先前往评价");
		List<TeacherEvaluateVO> myselfTeacherEvaluateList = oldTeacherEvaluateList.stream().map(oldTeacherEvaluate -> {
			TeacherEvaluateVO evaluateVO = TeacherEvaluateWrapper.build().entityVO(oldTeacherEvaluate);
			CourseEntity courseEntity = courseService.getById(oldTeacherEvaluate.getCourseId());
			User user = userService.getById(oldTeacherEvaluate.getTeacherId());
			if (Func.isNotEmpty(courseEntity) && Func.isNotEmpty(user)){
				evaluateVO.setCourseName(courseEntity.getName());
				evaluateVO.setTeacherName(user.getRealName());
			}
			return evaluateVO;
		}).collect(Collectors.toList());


		return R.data(myselfTeacherEvaluateList);
	}


	@GetMapping("/myself-participate-list")
	@ApiOperationSupport(order = 3)
	@ApiOperation(value = "参与的培训计划", notes = "")
	public R myselfParticipateTrainingPlanlist(TrainingPlanVO trainingPlan, Query query) {
		List<Long> trainPlanIds=trainingPlanService.getUserTrainingPlanIds(AuthUtil.getUserId());
		if (null==trainPlanIds)return R.success("暂无数据");
		List<TrainingPlanEntity> trainingPlanEntityList=trainingPlanService.list(Wrappers.<TrainingPlanEntity>query().lambda()
			.in(TrainingPlanEntity::getId, trainPlanIds));

		//筛选 正在进行中的培训培训计划
//		List<TrainingPlanEntity> filterTrainingPlanList = trainingPlanEntityList.stream().
//			filter(trainingPlanEntity -> trainingPlanEntity.getEndTime().after(now) && trainingPlanEntity.getStartTime().before(now)).collect(Collectors.toList());
//		if (CollectionUtil.isEmpty(filterTrainingPlanList))  return  R.success("无即将过期的培训计划");
		LambdaQueryWrapper<TrainingPlanEntity> queryWrapper= new LambdaQueryWrapper<>();
		queryWrapper.in(TrainingPlanEntity::getId,trainPlanIds).orderByDesc(TrainingPlanEntity::getStartTime);
		if(ObjectUtil.isNotEmpty(trainingPlan.getSearchStartTime())) queryWrapper.gt(TrainingPlanEntity::getStartTime,trainingPlan.getSearchStartTime());
		if(ObjectUtil.isNotEmpty(trainingPlan.getSearchEndTime())) queryWrapper.lt(TrainingPlanEntity::getEndTime,trainingPlan.getSearchEndTime());
		if(ObjectUtil.isNotEmpty(trainingPlan.getPlanName())) queryWrapper.like(TrainingPlanEntity::getPlanName,trainingPlan.getPlanName());
		//筛选后的培训计划ids
		trainPlanIds=trainingPlanEntityList.stream().map(TrainingPlanEntity::getId).collect(Collectors.toList());

		IPage<TrainingPlanEntity> pages = trainingPlanService.page(Condition.getPage(query), queryWrapper);
		IPage<TrainingPlanVO> trainingPlanVOIPage = TrainingPlanWrapper.build().pageVO(pages);
		trainingPlanVOIPage.setRecords(trainingPlanService.trainingPlanDetail(trainPlanIds,trainingPlanVOIPage.getRecords()));//给每条培训计划赋予对应的课程详情
		return R.data(trainingPlanVOIPage);
	}


	/**
	 * 即将过期的培训计划
	 */
	@GetMapping("/myself-coming-expire-list")
	@ApiOperationSupport(order = 4)
	@ApiOperation(value = "即将过期的培训计划", notes = "")
	public R myselfComingTrainingPlanlist(@ApiIgnore @RequestParam Map<String, Object> trainingPlan, Query query) {
		List<Long> trainPlanIds=trainingPlanService.getUserTrainingPlanIds(AuthUtil.getUserId());
		if (null==trainPlanIds)return R.success("暂无数据");
		List<TrainingPlanEntity> trainingPlanEntityList=trainingPlanService.list(Wrappers.<TrainingPlanEntity>query().lambda()
			.in(TrainingPlanEntity::getId, trainPlanIds));

		Date now=new Date();
		//筛选 培训截止时间大于等于当前时间(表示未过期) && 培训截止时间-当前时间 小于15天内
		List<TrainingPlanEntity> filterTrainingPlanList = trainingPlanEntityList.stream().filter(trainingPlanEntity -> {
			long endTime = trainingPlanEntity.getEndTime().getTime();
			long nowTime = now.getTime();
			long daysTime = 15 * 24 * 60 * 60 * 1000;
			long diff = endTime - nowTime;
			return trainingPlanEntity.getEndTime().after(now) && diff <= daysTime;
		}).collect(Collectors.toList());
		if (CollectionUtil.isEmpty(filterTrainingPlanList))  return  R.success("无即将过期的培训计划");

		//筛选后的培训计划ids
		trainPlanIds=filterTrainingPlanList.stream().map(TrainingPlanEntity::getId).collect(Collectors.toList());
		IPage<TrainingPlanEntity> pages = trainingPlanService.page(Condition.getPage(query), Condition.getQueryWrapper(trainingPlan, TrainingPlanEntity.class)
			.in("id",trainPlanIds));
		IPage<TrainingPlanVO> trainingPlanVOIPage = TrainingPlanWrapper.build().pageVO(pages);
		trainingPlanVOIPage.setRecords(trainingPlanService.trainingPlanDetail(trainPlanIds,trainingPlanVOIPage.getRecords()));//给每条培训计划赋予对应的课程详情
		return R.data(trainingPlanVOIPage);
	}

	/**
	 * 即将开始的培训计划
	 */
	@GetMapping("/myself-coming-start-list")
	@ApiOperationSupport(order = 5)
	@ApiOperation(value = "即将开始的培训计划", notes = "")
	public R myselfComingStartTrainingPlanlist(@ApiIgnore @RequestParam Map<String, Object> trainingPlan, Query query) {
		List<Long> trainPlanIds=trainingPlanService.getUserTrainingPlanIds(AuthUtil.getUserId());
		if (null==trainPlanIds)return R.success("暂无数据");
		List<TrainingPlanEntity> trainingPlanEntityList=trainingPlanService.list(Wrappers.<TrainingPlanEntity>query().lambda()
			.in(TrainingPlanEntity::getId, trainPlanIds));
		Date now=new Date();
		//筛选 培训开始间大于等于当前时间(表示未开始) && 培训开始时间小于当前时间15天内
		List<TrainingPlanEntity> filterTrainingPlanList = trainingPlanEntityList.stream().filter(trainingPlanEntity -> {
			long startTime = trainingPlanEntity.getStartTime().getTime();
			long nowTime = now.getTime();
			long daysTime = 15 * 24 * 60 * 60 * 1000;
			long diff = startTime - nowTime;
			return trainingPlanEntity.getStartTime().after(now) && diff <= daysTime;
		}).collect(Collectors.toList());
		if (CollectionUtil.isEmpty(filterTrainingPlanList))  return  R.success("无即将开始的培训计划");

		//筛选后的培训计划ids
		trainPlanIds=filterTrainingPlanList.stream().map(TrainingPlanEntity::getId).collect(Collectors.toList());
		IPage<TrainingPlanEntity> pages = trainingPlanService.page(Condition.getPage(query), Condition.getQueryWrapper(trainingPlan, TrainingPlanEntity.class)
			.in("id",trainPlanIds));
		IPage<TrainingPlanVO> trainingPlanVOIPage = TrainingPlanWrapper.build().pageVO(pages);
		trainingPlanVOIPage.setRecords(trainingPlanService.trainingPlanDetail(trainPlanIds,trainingPlanVOIPage.getRecords()));//给每条培训计划赋予对应的课程详情
		return R.data(trainingPlanVOIPage);
	}

	/**
	 * 记录上次浏览的培训记录
	 */
	@GetMapping("/record-browse-list")
	@ApiOperationSupport(order = 6)
	@ApiOperation(value = "记录上次浏览的培训记录", notes = "")
	public R myselfRecordBrowseTrainingPlan(Long trainingPlanId) {
		if (ObjectUtil.isEmpty(trainingPlanId)) return R.success("记录成功");
		Long userId=AuthUtil.getUserId();
		ThreadPool.execute(new Runnable() {
			@Override
			public void run() {
				bladeRedis.set(RedisKeyConstant.TRAINING_PLAN_BROWSE+userId,trainingPlanId);
			}
		});
		return R.success("记录成功");
	}

	/**
	 * 获取上次浏览的培训记录
	 */
	@GetMapping("/myself-browse-list")
	@ApiOperationSupport(order = 7)
	@ApiOperation(value = "获取上次浏览的培训记录", notes = "")
	public R myselfBrowseTrainingPlan(@ApiIgnore @RequestParam Map<String, Object> trainingPlan, Query query) {
		Long userId=AuthUtil.getUserId();
		Long trainPlanId = bladeRedis.get(RedisKeyConstant.TRAINING_PLAN_BROWSE + userId);
		if (null==trainPlanId)return R.success("无浏览记录");

		List<Long> trainPlanIds=new ArrayList<>();
		trainPlanIds.add(trainPlanId);
		List<TrainingPlanVO> trainingPlanEntityList=trainingPlanService.list(Wrappers.<TrainingPlanEntity>query().lambda()
			.in(TrainingPlanEntity::getId, trainPlanIds)).stream()
			.map(trainingPlanEntity -> TrainingPlanWrapper.build().entityVO(trainingPlanEntity)).collect(Collectors.toList());

		return R.data(trainingPlanService.trainingPlanDetail(trainPlanIds,trainingPlanEntityList));
	}



	/**
	 * 获取该用户所有的培训计划
	 */
	@GetMapping("/myself-record-list")
	@ApiOperationSupport(order = 8)
	@ApiOperation(value = "培训记录", notes = "")
	public R myselfTrainingPlanCompleteRecord(TrainingPlanVO trainingPlan, Query query) {
		List<Long> trainPlanIds=trainingPlanService.getUserTrainingPlanIds(AuthUtil.getUserId());
		if (null==trainPlanIds)return R.success("无记录");
		LambdaQueryWrapper<TrainingPlanEntity> queryWrapper= new LambdaQueryWrapper<>();
		queryWrapper.in(TrainingPlanEntity::getId,trainPlanIds).orderByDesc(TrainingPlanEntity::getStartTime);
		if(ObjectUtil.isNotEmpty(trainingPlan.getSearchStartTime())) queryWrapper.gt(TrainingPlanEntity::getStartTime,trainingPlan.getSearchStartTime());
		if(ObjectUtil.isNotEmpty(trainingPlan.getSearchEndTime())) queryWrapper.lt(TrainingPlanEntity::getEndTime,trainingPlan.getSearchEndTime());
		if(ObjectUtil.isNotEmpty(trainingPlan.getPlanName())) queryWrapper.like(TrainingPlanEntity::getPlanName,trainingPlan.getPlanName());
		//获取所有培训计划
		IPage<TrainingPlanEntity> pages = trainingPlanService.page(Condition.getPage(query), queryWrapper);
		IPage<TrainingPlanVO> trainingPlanVOIPage = TrainingPlanWrapper.build().pageVO(pages);

		trainingPlanVOIPage.setRecords(trainingPlanService.trainingPlanDetail(trainPlanIds,trainingPlanVOIPage.getRecords()));
		return R.data(trainingPlanVOIPage);

	}


}
